/*
 * @Author: ygnnli 1585923072@qq.com
 * @Date: 2024-08-16 14:23:52
 * @LastEditors: ygnnli 1585923072@qq.com
 * @LastEditTime: 2024-08-20 23:02:28
 * @FilePath: /bitrpc/source/dispatcher.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once
#include "net.hpp"
#include "message.hpp"

namespace bitrpc
{
    // 回调函数基类
    class Callback
    {
    public:
        using ptr = std::shared_ptr<Callback>;
        virtual void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg) = 0;
    };

    template <typename T>
    class CallbackT : public Callback
    {
    public:
        using ptr = std::shared_ptr<CallbackT<T>>;
        using MessageCallback = std::function<void(const BaseConnection::ptr &conn, std::shared_ptr<T> &msg)>;
        
        CallbackT(const MessageCallback &handler) : _handler(handler) {}
        void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg) override
        {
            auto type_msg = std::dynamic_pointer_cast<T>(msg);
            _handler(conn, type_msg);
        }

    private:
        MessageCallback _handler; // 回调函数 管理不同类型的回调函数
    };

    // 消息分发器
    class Dispatcher
    {
    public:
        using ptr = std::shared_ptr<Dispatcher>;
        // 注册消息回调函数
        template <typename T>
        void registerhandler(MType mtype, const typename CallbackT<T>::MessageCallback &handler)
        {
            //ELOG("注册消息回调函数!");
            std::unique_lock<std::mutex> lock(_mutex);         // 互斥锁
            auto cb = std::make_shared<CallbackT<T>>(handler); // 创建回调函数
            _handlers.insert(std::make_pair(mtype, cb));       // 插入消息回调函数
        }
        // 处理消息
        void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg)
        {
            //ELOG("onMessage收到消息");
            // 找到消息类型对应的业务处理函数，进行调用即可
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _handlers.find(msg->mtype()); // 查找消息类型对应的处理回调函数
            if (it != _handlers.end())              // 找到了
            {
                return it->second->onMessage(conn, msg);
            }
            // 没有找到指定类型的处理回调--因为客户端和服务端都是我们自己设计的，因此不可能出现这种情况
            ELOG("收到未知类型的消息: %d!", (int)msg->mtype());
            conn->shutdown();
        }

    private:
        std::mutex _mutex;                                  // 互斥锁
        std::unordered_map<MType, Callback::ptr> _handlers; // 消息回调函数
    };

}